#include "StdAfx.h"
#include "ledImage.h"
#include "common.h"
#include <math.h>
#include <assert.h>

ledImage::ledImage(unsigned radius, unsigned portion, unsigned leaf, class CledDlg *dlg):m_radius(radius), m_portion(portion), m_leaf(leaf),m_dlg(dlg)
{
	m_file = 0;
	m_pos = new CPoint[m_portion*m_leaf*radius];
	assert(m_pos);
	putPos();
}

ledImage::~ledImage(void)
{
	if(m_file)
		fclose(m_file);
	if(m_pos)
		delete m_pos;
}

int ledImage::open(CString name)
{
	if(m_file)
		fclose(m_file);

	m_file = fopen(name.GetBuffer(0), "wb");
	if(!m_file)
		return -1;
	
	char buf[32] = {0};
	struct file_head *head = (struct file_head *)buf;

	head->radius = m_radius;
	head->portion = m_portion;
	head->leaf = m_leaf;

	int err = fwrite("led!", 4, 1, m_file);
	err = fwrite(head, 28, 1, m_file);

	return 0;
}

void ledImage::close()
{
	if(m_file)
		fclose(m_file);

	m_file = 0;
}

void ledImage::writeLinePos(unsigned point)
{
	unsigned size = m_radius;
	double argle = (2 * PI * point)/(m_portion*m_leaf);

	double s_y = sin(argle);
	double s_x = cos(argle);
			
	for(int j = m_radius-1; j >= (int)(m_radius - size); j--){
		int x = m_radius + j*s_x;
		int y = m_radius + j*s_y;

		m_pos[point*m_radius + j].x = x;
		m_pos[point*m_radius + j].y = y;
	}
}

void ledImage::putPos()
{
	for(unsigned i = 0; i < m_portion*m_leaf; i++){
		writeLinePos(i);
	}
}

int ledImage::writeLine(CImage *image, struct line_head *head, unsigned point)
{
	unsigned char *pcolor = (unsigned char *)(head+1);
			
	for(int j = m_radius-1; j >= 0; j--){
		COLORREF pixel = image->GetPixel(m_pos[point*m_radius + j].x, m_pos[point*m_radius + j].y);

		pcolor[((m_radius-1)-j)*3 + 0] = GetBValue(pixel);
		pcolor[((m_radius-1)-j)*3 + 1] = GetGValue(pixel);
		pcolor[((m_radius-1)-j)*3 + 2] = GetRValue(pixel);
	}
			
	head->head.len = 3*m_radius + sizeof(struct line_head) - sizeof(struct led_head);
	head->point = point;
	assert(head->head.magic == LED_MAGIC);
	assert(head->head.type == LED_TYPE_LINE);

	return 1 == fwrite(head, sizeof(head->head) + head->head.len, 1, m_file) ? 0 : -1;
}

int ledImage::write(CImage *pic, uint32_t time)
{
	if(!m_file)
		return -1;

	CImage *image = pic;
	if(image->GetHeight() != image->GetWidth() || image->GetHeight() != m_radius * 2){
		image = CreateStretchImage(pic, m_radius*2, m_radius*2);
		if(!image)
			return -1;
	}

	m_dlg->drawImage(image);

	struct pic_head picHead;
	picHead.head.magic = LED_MAGIC;
	picHead.head.type = LED_TYPE_PIC;
	picHead.head.len = sizeof(struct pic_head) - sizeof(struct led_head);
	picHead.time = time;
	fwrite(&picHead, sizeof(picHead), 1, m_file);

	struct line_head *head = (struct line_head *)malloc(sizeof(head) + 3*(m_radius + 1));
	unsigned char *pcolor = (unsigned char *)(head+1);
	head->head.magic = LED_MAGIC;
	head->head.type = LED_TYPE_LINE;

	for(unsigned i = 0; i < m_portion; i++){
		for(unsigned j = 0; j < m_leaf; j++){
			writeLine(image, head, i + j*m_portion);
		}
	}

	if(pic != image){
		image->Destroy();
		delete image;
	}

	free(head);
	return 0;
}
